<?php
declare(strict_types=1);
namespace SixShop\Lakala\Service;

use SixShop\Lakala\OpenAPISDK\V3\Api\LakalaApi;
use SixShop\Lakala\OpenAPISDK\V3\Api\QueryTradequeryApi;
use SixShop\Lakala\OpenAPISDK\V3\Api\TransPreorderApi;
use SixShop\Lakala\OpenAPISDK\V3\Configuration;
use SixShop\Lakala\OpenAPISDK\V3\Model\ModelRequest;
use SixShop\Lakala\OpenAPISDK\V3\Model\QueryTradequeryRequest;
use SixShop\Lakala\OpenAPISDK\V3\Model\TradeAccBusiFields;
use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaAccBusiFields;
use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaDetail;
use SixShop\Lakala\OpenAPISDK\V3\Model\TradePreorderWechaGoodsDetail;
use SixShop\Lakala\OpenAPISDK\V3\Model\TransPreorderRequest;
use SixShop\Lakala\Config;
use SixShop\Lakala\Dto\LocationInfo;
use think\facade\Log;
use function SixShop\Core\throw_logic_exception;

/**
 * TransactionService
 */
class TransactionService
{
    private TransPreorderApi $transPreorderApi;

    private QueryTradequeryApi $queryTradequeryApi;

    private LakalaApi $lakalaApi;
    public function __construct(private Config $config)
    {
        $this->transPreorderApi = new TransPreorderApi($config->getV3Config());
        $this->queryTradequeryApi = new QueryTradequeryApi($config->getV3Config());
        $this->lakalaApi = new LakalaApi($config->getV3Config());
    }

    /**
     * 聚合主扫
     * @param string $outTradeNo 商户交易流水号
     * @param float $totalAmount 交易金额
     * @param LocationInfo $locationInfo 地理位置信息
     * @param string $accountType 账户类型 微信：WECHAT 支付宝：ALIPAY 银联：UQRCODEPAY 翼支付: BESTPAY 苏宁易付宝: SUNING 拉卡拉支付账户：LKLACC 网联小钱包：NUCSPAY 京东钱包：JD
     * @param string $transType 交易类型 41:NATIVE（（ALIPAY，云闪付支持，京东白条分期） 51:JSAPI（微信公众号支付，支付宝服务窗支付，银联JS支付，翼支付JS支付, 拉卡拉钱包支付, 京东白条分期） 71:微信小程序支付 61:APP支付（微信APP支付）
     * @param string $busiMode 业务模式 ACQ-收单 不填，默认为“ACQ-收单”
     * @param string $subject 交易标题
     * @param string $payOrderNo 拉卡拉订单系统订单号，以拉卡拉支付业务订单号为驱动的支付行为，需上传该字段。
     * @param string $settleType 结算类型 “0”或者空，常规结算方式，如需接拉卡拉分账通需传“1”，商户未开通分账之前切记不用上送此参数。
     * @param string $remark 备注
     * @param object $accBusiFields 账户端业务信息域
     *
     * @link https://o.lakala.com/#/home/document/detail?id=110
     */
    public function preOrder(
        string $outTradeNo,
        float $totalAmount,
        LocationInfo $locationInfo,
        string $accountType = 'WECHAT',
        string $transType = '71',
        string $busiMode = 'ACQ',
        string $subject = '',
        string $payOrderNo = '',
        string $settleType = '',
        string $remark = '',
        TradeAccBusiFields $accBusiFields = null,
    ):object
    {
        $request = new TransPreorderRequest();

        $request->setMerchantNo($this->config->merchant_no);
        $request->setTermNo($this->config->term_no);
        $request->setOutTradeNo($outTradeNo);
        $request->setAccountType($accountType);
        $request->setTransType($transType);
        $totalAmount = round($totalAmount * 100, 0);
        $request->setTotalAmount($totalAmount); // 单位分
        $request->setLocationInfo($locationInfo);

        // 非必填参数
        $request->setBusiMode($busiMode);
        $request->setSubject($subject);
        $request->setPayOrderNo($payOrderNo);
        $request->setNotifyUrl($this->config->notify_url);
        $request->setSettleType($settleType);
        $request->setRemark($remark);
        $request->setAccBusiFields($accBusiFields);
        $request->setCompleteNotifyUrl($this->config->complete_notify_url);
        Log::debug('preOrder request:'.json_encode($request));
        $response = $this->transPreorderApi->transPreorder($request);
        Log::debug('preOrder response:'.json_encode($response->getRespData()));
        if ($response->getCode() == 'BBS00000') {
            return $response->getRespData();
        } else {
            throw_logic_exception(
                msg:$response->getMsg(),
                status: $response->getCode(),
                data: $response->getRespData(),
            );
        }
    }

    /**
     * 聚合扫码-交易查询
     *
     * 下单时的商户请求流水号 说明：out_trade_no、trade_no、必有其一。如果存在多个字段上送，优先级顺序如下： trade_no、 out_trade_no
     *
     * @param string $tradeNo 拉卡拉订单系统订单号
     * @param string $outTradeNo 商户订单号
     */
    public function queryTrade(string $tradeNo = '', string $outTradeNo = ''):object
    {
        $request = new QueryTradequeryRequest();
        $request->setMerchantNo($this->config->merchant_no);
        $request->setTermNo($this->config->term_no);
        $request->setTradeNo($tradeNo);
        $request->setOutTradeNo($outTradeNo);
        $response = $this->queryTradequeryApi->queryTradequery($request);

        if ($response->getCode() == 'BBS00000') {
            return $response->getRespData();
        } else {
            throw_logic_exception(
                msg:$response->getMsg(),
                status: $response->getCode(),
                data: $response->getRespData(),
            );
        }
    }

    /**
     * 聚合扫码-交易退款
     *
     * @param string $refundTradeNo 退款订单号
     * @param string $refundAmount 退款金额
     * @param LocationInfo $locationInfo 地理位置信息
     * @param string $originTradeNo 原交易拉卡拉交易订单号
     * @param string $originOutTradeNo 原商户订单号
     * @param string $refundReason 退款原因
     * @link https://o.lakala.com/#/home/document/detail?id=892
     */
    public function refund(
        string $refundTradeNo,
        float $refundAmount,
        LocationInfo $locationInfo,
        string $originTradeNo = '',
        string $originOutTradeNo = '',
        string $refundReason = '',
    )
    {
        $request = new ModelRequest();
        $reqData = [
            'merchant_no' => $this->config->merchant_no,
            'term_no' => $this->config->term_no,
            'out_trade_no' => $refundTradeNo,
            'refund_amount' => round($refundAmount*100),
            'refund_reason' => $refundReason,
            'origin_out_trade_no' => $originOutTradeNo,
            'origin_trade_no' => $originTradeNo,
            'location_info' => $locationInfo->jsonSerialize(),
            'notify_url' => $this->config->notify_url,
            'refund_amt_sts' => '00'
        ];
        $request->setReqData($reqData);
        $response = $this->lakalaApi->tradeApi('/api/v3/rfd/refund_front/refund', $request);
        if ($response->getCode() == '000000') {
            return $response->getRespData();
        } else {
            throw_logic_exception(
                msg:$response->getMsg(),
                status: $response->getCode(),
                data: $response->getRespData(),
            );
        }
    }
}